/*
  Copyright (c) 2011, Mikheev Rostislav
  Copyright (c) 2011, FreshFarsh team

  Steel Engine source code is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
/**
  @file control.h
  @author Mikheev Rostislav <hacenator@gmail.com>
  @date 13.03.2011
  @brief GUI Control element base class header file.
*/
#ifndef STEEL_GUI_CONTROL_H_
#define STEEL_GUI_CONTROL_H_

#include <stdint.h>
#include "common.h"
#include "structures.h"
#include "basic_class.h"

namespace _STEEL_NAMESPACE {

typedef uint32_t GUIControlId; ///< GUI control unified identifier
typedef char* GUIControlName; ///< GUI control name

// User interface callback funtions
/// GUI Default callback (for click, OnShow, OnHide and e.t.c)
typedef void (* GUICallback)(const void*);

/// GUI Mouse over callback
typedef void (* GUIMoveOverCallback)(const void*, int x, int y);

/// GUI Mouse out callback
typedef void (* GUIMoveOutCallback)(const void*);

/// GUI Key Down callback
typedef void (* GUIKeyDownCallback)(const void*, int key);

/// GUI Key Up callback
typedef void (* GUIKeyUpCallback)(const void*, int key);

/// GUI Focus got callback
typedef void (* GUIFocusGetCallback)(const void*);

/// GUI Focus lost callback
typedef void (* GUIFocusLostCallback)(const void*);

/// GUI Mouse Down callback
typedef void (* GUIMouseDownCallback)(const void*, int x, int y);

/// GUI Mouse Up callback
typedef void (* GUIMouseUpCallback)(const void*, int x, int y);

/// GUI Mouse move callback
typedef void (* GUIMouseMoveCallback)(const void*, int x, int y);

/**
 * Keyboard key enumerator
 * kUp - key is up
 * kDown - key is down
 */
enum GUIKeyState {
  kKeyUp = 1,
	kKeyDown = 0
};

/**
 * Mouse button enumerator
 */
enum GUIMouseButton {
  kMouseLeft,
  kMouseRight,
  kMouseMiddle
};

/**
 * Mouse state enumerator
 */
enum GUIMouseButtonState {
	kMouseDown,
	kMouseUp,
	//kMouseWheelUp, // mouse wheel
	//kMouseWheelDown // mouse wheel
	//kMouseMove /// touchpad
};

/**
 * Mouse wheel enumerator
 */
enum GUIMouseWheelState {
	kMouseWheelUp,
	kMouseWheelDown,
	kMouseWheelIdle
};

/**
 * Mouse structure
 */
struct GUIMouse {
  GUIMouseButtonState left_button; ///< left mouse button state
  GUIMouseButtonState right_button; ///< right mouse button state
  GUIMouseButtonState middle_button; ///< right mouse button state
  GUIMouseWheelState wheel; ///< right mouse button state
};

/**
 * GUI Skin Structure
 * Store GUI Skin textures and parameters
 */
struct GUISkin {
  // window texture
  // button texture
  // edit texture
  // list texture
  // font
  // font color
};

/**
 * GUI Control ellements basic class
 */
class GUIControl : public BasicClass {
 public:
  GUIControl();
  GUIControl(const char * name);
  virtual ~GUIControl();

  /**
   * Element Draw
   */
  virtual void Draw() {};

  // accesors
  /**
   * Get element identificator
   * @return
   *      Element numeric id
   */
  virtual GUIControlId Id() {
    return _id;
  };

  /**
   * Setting element identificator
   * @param id
   *      New identificator
   * @return
   *      Return true if ide succesfully set, and false otherwise
   */
  virtual bool set_id(GUIControlId id);

  /**
   * Setting element name
   */
  virtual const char * set_name(const char * name);

  /**
   * Getting element name
   */
  virtual const char * name() {
    return _name;
  };

  // Position and view controll
  /**
   * Show element
   */
  void Show();

  /**
   * Hide element
   */
  void Hide();

  /**
   * Visiblity state
   * @return value
   *  If return true - element is visible, hidden otherwise
   */
  bool visible() {
    return _visible;
  };

  /**
   * Return element width
   * @return
   *      Element width value
   */
  virtual double width() {
    return _width;
  };

  /**
   * Set element width
   * @param value
   *      Element width value
   */
  virtual void set_width(int value);

  /**
   * Return element height
   * @return
   *      Element height value
   */
  virtual double height() {
    return _height;
  };

  /**
   * Set element height
   * @return
   *      Element height value
   */
  virtual void set_height(int value);

  /**
   * Return x position
   * @return
   *      Element x position
   */
  virtual double x() {
    return _x;
  };

  /**
   * Set x position
   * @param value
   *      Element x position
   */
  virtual void set_x(int value) {
    _x = value;
  }

  /**
   * Return y position
   * @return
   *      Element y position
   */
  virtual double y() {
    return _y;
  };

  /**
   * Set element y position
   * @return value
   *      Element y position
   */
  virtual void set_y(int value) {
    _y = value;
  }

  /**
   * Return element rect
   * @return
   *      Element rect
   */
  virtual Rect GetControlRect();

  // Events
  virtual void Click(const GUIControl * sender);
  virtual void MoveOver(const GUIControl * sender, int x, int y);
  virtual void MoveOut(const GUIControl * sender);
  virtual void KeyUp(const GUIControl * sender, int key);
  virtual void KeyDown(const GUIControl * sender, int key);
  virtual void FocusGet(const GUIControl * sender);
  virtual void FocusLost(const GUIControl * sender);
  virtual void MouseDown(const GUIControl * sender, int x, int y);
  virtual void MouseUp(const GUIControl * sender, int x, int y);
  virtual void MouseMove(const GUIControl * sender, int x, int y);

  // events setters
  /// Set OnClick event
  virtual void OnClick(GUICallback callback) {
    _on_click = callback;
  };

  /// Set onMouseOver event
  virtual void OnMoveOver(GUIMoveOverCallback callback) {
    _on_mouse_move_over = callback;
  };

  /// Set onMouseOut event
  virtual void OnMoveOut(GUIMoveOutCallback callback) {
    _on_mouse_move_out = callback;
  };

  /// Set onKeyUp event
  virtual void OnKeyUp(GUIKeyUpCallback callback) {
    _on_key_up = callback;
  };

  /// Set onKeyDown event
  virtual void OnKeyDown(GUIKeyDownCallback callback) {
    _on_key_down = callback;
  };

  /// Set onFocusGet event
  virtual void OnFocusGet(GUIFocusGetCallback callback) {
    _on_focus_get = callback;
  };

  /// Set onFocusLost event
  virtual void OnFocusLost(GUIFocusLostCallback callback) {
    _on_focus_lost = callback;
  };

  /// Set onMouseDown event
  virtual void OnMouseDown(GUIMouseDownCallback callback) {
    _on_mouse_down = callback;
  };

  /// Set onMouseUp event
  virtual void OnMouseUp(GUIMouseUpCallback callback) {
    _on_mouse_up = callback;
  };

  /// Set onMouseMove event
  virtual void OnMouseMove(GUIMouseMoveCallback callback) {
    _on_mouse_move = callback;
  };

 protected:
  GUIControlId _id; ///< control element unified identificator
  GUIControlName _name; ///< element name
  bool _visible; ///< element visiblity state
  int _x, _y; ///< element x, y positions
  int _height, _width; ///< element size

  // TODO(hacenator): (z-index, font color, font family, font size) must be usefull

  void * _parent; ///< paren element pointer

  bool _focused; ///< element is focused

  // callbacks
	GUICallback _on_click;
  GUIMoveOverCallback _on_mouse_move_over;
  GUIMoveOutCallback _on_mouse_move_out;
  GUIKeyDownCallback _on_key_down;
  GUIKeyUpCallback _on_key_up;
  GUIFocusGetCallback _on_focus_get;
  GUIFocusLostCallback _on_focus_lost;
  GUIMouseDownCallback _on_mouse_down;
  GUIMouseUpCallback _on_mouse_up;
  GUIMouseMoveCallback _on_mouse_move;

};

}

#endif /* STEEL_GUI_CONTROL_H_ */
